home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / lib / c / etc / pdev.c < prev    next >
C/C++ Source or Header  |  1990-06-27  |  40KB  |  1,351 lines

  1. /* 
  2.  * pdev.c --
  3.  *
  4.  *    The routines in this module set up a call-back interface for
  5.  *    a pseudo-device server.  Pdev_Open creates a pseudo-device and
  6.  *    installs service procedures.  These service procedures are called
  7.  *    when client processes use the pseudo-device.  The harness procedure
  8.  *    which invokes the call-backs takes care of the kernel interface.
  9.  *    There are also default service procedures so the user of Pdev_Open
  10.  *    need only provide service procedures for the operations of interest.
  11.  *
  12.  * Copyright 1989 Regents of the University of California
  13.  * Permission to use, copy, modify, and distribute this
  14.  * software and its documentation for any purpose and without
  15.  * fee is hereby granted, provided that the above copyright
  16.  * notice appear in all copies.  The University of California
  17.  * makes no representations about the suitability of this
  18.  * software for any purpose.  It is provided "as is" without
  19.  * express or implied warranty.
  20.  */
  21.  
  22. #ifndef lint
  23. static char rcsid[] = "$Header: /sprite/src/lib/c/etc/RCS/pdev.c,v 1.15 90/06/27 11:17:12 shirriff Exp $ SPRITE (Berkeley)";
  24. #endif not lint
  25.  
  26. #include <stdio.h>
  27. #include <sprite.h>
  28. #include <ctype.h>
  29. #include <errno.h>
  30. #include <pdev.h>
  31. #include <list.h>
  32. #include <status.h>
  33. #include <stdlib.h>
  34. #include <string.h>
  35. #include <sys/file.h>
  36.  
  37. /*
  38.  * The string below holds an error message if Pdev_Open fails.
  39.  */
  40.  
  41. char pdev_ErrorMsg[150];
  42.  
  43. /*
  44.  * Boolean that can be toggled by applications to get tracing.
  45.  */
  46. int pdev_Trace;
  47.  
  48. /*
  49.  * The Pdev structure is the top-level state for the pseudo-device
  50.  * or pseudo-filelsystem server.  The state for each pseudo-device connection
  51.  * is hung in a list off of this.  This also has a set of default service
  52.  * procedures for the various pseudo-device operations.  Two
  53.  * fields of the Pdev struct are made available to the client of the
  54.  * Pdev package so it can do IOControls on the service stream and
  55.  * set a private data pointer.
  56.  */
  57.  
  58. typedef struct Pdev {
  59.     Pdev_Stream stream;        /* Type PDEV_MAGIC */
  60.     List_Links connectList;    /* List of all service streams for this
  61.                  * pseudo-device (pseudo-filesystem). */
  62.     int requestBufSize;        /* Default request buffer size */
  63.     int readBufSize;        /* Size for optional read buffer */
  64.     Pdev_CallBacks *defaultService;/* Default handlers for pdev operations */
  65. } Pdev;
  66.  
  67. /*
  68.  * The structure below corresponds to a pseudo-device connection between
  69.  * a client and the server.
  70.  */
  71.  
  72. typedef struct ServiceStream {
  73.     Pdev_Stream stream;        /* Type PDEV_STREAM_MAGIC */
  74.     List_Links links;        /* pdev streams are linked into a
  75.                  * list of all streams for the same
  76.                  * pseudo-device (pseudo-file-system). */
  77.     Address parent;        /* Pdev state with which this stream is
  78.                  * associated. */
  79.     int streamID;        /* Sprite identifier for request stream. */
  80.     Address requestBuf;        /* A buffer for requests and data from the
  81.                  * client */
  82.     Address readBuf;        /* A buffer for data to be read over the
  83.                  * pseudo-device by the application. This
  84.                  * is allocated by us and passed to the
  85.                  * read call-back. If read buffering is set
  86.                  * then we allocate this at open-time and
  87.                  * pass it off to the open call-back. */
  88.     int readBufSize;        /* Size of the readBuf. */
  89.     Address ioctlOutBuf;    /* Buffer for results of ioctl */
  90.     int ioctlBufSize;        /* Size of ioctlOutBut */
  91.     Pdev_CallBacks *service;    /* Set of procedures to handle the various
  92.                  * pseudo-device operations. */
  93. } ServiceStream;
  94.  
  95. #define LIST_TO_SRVPTR(listPtr) \
  96.     (ServiceStream *)((int)(listPtr) - sizeof(Pdev_Stream))
  97.  
  98. static int    PdevDefaultOpen();
  99. static int    PdevDefaultRead();
  100. static int    PdevDefaultWrite();
  101. static int    PdevDefaultIoctl();
  102. static int    PdevDefaultClose();
  103. static int    PdevDefaultGetAttr();
  104. static int    PdevDefaultSetAttr();
  105.  
  106. static Pdev_CallBacks pdevDefaultCallBacks = {
  107.      PdevDefaultOpen,
  108.      PdevDefaultRead,
  109.      PdevDefaultWrite,
  110.      PdevDefaultIoctl,
  111.      PdevDefaultClose,
  112.      PdevDefaultGetAttr,
  113.      PdevDefaultSetAttr,
  114. };
  115.  
  116. /*
  117.  * PDEV_MIN_BYTES        Minimum number of data bytes in request buffer.
  118.  * PFS_REQUEST_BUF_SIZE     Size of the request buffer for naming stream.
  119.  */
  120.  
  121. #define PDEV_MIN_BYTES    1024
  122. #define PDEV_REQUEST_BUF_SIZE    (sizeof(Pdev_Request) + PDEV_MIN_BYTES)
  123.  
  124. /*
  125.  * Forward references to procedures in this file:
  126.  */
  127.  
  128. static void    PdevControlRequest();
  129. static void    PdevServiceRequest();
  130. static int    PdevCleanup();
  131. static void    ReplyNoData();
  132. static void    ReplyWithData();
  133. static int    (*SetHandler())();
  134.  
  135. /*
  136.  *----------------------------------------------------------------------
  137.  *
  138.  * Pdev_Open --
  139.  *
  140.  *    Arrange to be the server for a pseudo-device.  This creates the
  141.  *    pseudo-device file, choosing a unique name if needed (see below).
  142.  *    The set of service call-backs are installed and will be called
  143.  *    when regular processes operate on the pseudo-device.  See the
  144.  *    man page for Pdev for details of the call-back interface.
  145.  *
  146.  * Results:
  147.  *    The return value is a token for the pseudo-device, which gets
  148.  *    passed to Pdev_Close.  A NULL return value
  149.  *    means that the pseudo-device could not be opened.  If realNamePtr
  150.  *    is non-NULL, *realNamePtr is filled in with a dynamically-
  151.  *    allocated string giving the actual name of the pseudo-device
  152.  *    file.
  153.  *
  154.  * Side effects:
  155.  *    A pseudo-device is opened in master mode.  If realNamePtr is
  156.  *    NULL then name is the complete name of the pseudo device;  if
  157.  *    realNamePtr is not NULL, then this procedure generates a
  158.  *    pseudo-device name of the form hostDir/nameXX, where "hostDir"
  159.  *    is the name of a standard host-specific directory for holding
  160.  *    terminal pseudo-devices and XX is an integer id appended to
  161.  *    "name" in order to find a device that isn't already in use.
  162.  *    Once this procedure returns, this module manages the pseudo
  163.  *    device to provide a simple call-back interface to service procedures.
  164.  *    I,e, for each operation on the pseudo-device by a another process,
  165.  *    a call-back for that operation is made to one of the supplied
  166.  *    service procedures.
  167.  *
  168.  *----------------------------------------------------------------------
  169.  */
  170.  
  171. Pdev_Token
  172. Pdev_Open(name, realNamePtr, requestBufSize, readBufSize, service, clientData)
  173.     char *name;            /* Name of pseudo-device file to use for
  174.                  * application interface, or key for generating
  175.                  * name (if realNamePtr != NULL).  If no
  176.                  * pseudo-device by that name exists, one
  177.                  * will be created. */
  178.     char **realNamePtr;        /* If not NULL, then use "name" as a key for
  179.                  * a name (see above) and store actual name of
  180.                  * pseudo-device here.  The memory for the
  181.                  * string is dynamically allocated. */
  182.     int requestBufSize;        /* Preferred size for the request buffer.
  183.                  * Can be <= 0 for a default size */
  184.     int readBufSize;        /* Size for optional read buffer.  Zero means
  185.                  * no buffering and we use the read call-back*/
  186.     Pdev_CallBacks *service;    /* A set of service procedures.
  187.                  * This can be NULL (or any element can be
  188.                  * NULL) in order to get a default handler
  189.                  * for all (some) operations.  The callbacks
  190.                  * can be changed with Pdev_SetupHandler */
  191.     ClientData clientData;    /* Client data associated with pseudo-device */
  192. {
  193.     int streamID;
  194.     register Pdev *pdevPtr;
  195.     int pdevOpenFlags;
  196.  
  197.     /*
  198.      * Pick a file name to use for the pseudo-device, if the caller didn't
  199.      * give us one, then open the pseudo-device as the controlling process.
  200.      */
  201.  
  202.     pdevOpenFlags = O_MASTER|O_RDWR|O_CREAT;
  203.     if (realNamePtr != NULL) {
  204.     char hostName[50];
  205.     int i;
  206.     char *actualName;
  207.  
  208.     if (gethostname(hostName, 20) != 0) {
  209.         sprintf(pdev_ErrorMsg, "couldn't get host name (%s)",
  210.             strerror(errno));
  211.         return (Pdev_Token) NULL;
  212.     } else {
  213.         /*
  214.          * Trim off domain name, if any
  215.          */
  216.         char *cp;
  217.  
  218.         cp = index(hostName, '.');
  219.         if (cp != (char *)NULL) {
  220.         *cp = '\0';
  221.         }
  222.     }
  223.     actualName = (char *) malloc((unsigned) (12 + strlen(hostName)
  224.         + strlen(name)));
  225.     for (i = 1; i < 100; i++) {
  226.         sprintf(actualName, "/hosts/%s/%s%d", hostName,
  227.             name, i);
  228.  
  229.         /*
  230.          * Because of umask, the file's mode may not actually get set
  231.          * to 0666.  Once the file is open, change the mode explicitly
  232.          * to force it.
  233.          */
  234.  
  235.         streamID = open(actualName, pdevOpenFlags, 0666);
  236.         if (streamID >= 0) {
  237.         fchmod(streamID, 0666);
  238.         *realNamePtr = actualName;
  239.         goto gotStream;
  240.         }
  241.     }
  242.     free((char *) actualName);
  243.     sprintf(pdev_ErrorMsg, 
  244.         "couldn't open a pseudo-device in \"/hosts/%s\"", hostName);
  245.     return (Pdev_Token) NULL;
  246.     } else {
  247.     streamID = open(name, pdevOpenFlags, 0666);
  248.     if (streamID < 0) {
  249.         sprintf(pdev_ErrorMsg, "couldn't open \"%s\" (%s)",
  250.             name, strerror(errno));
  251.         return (Pdev_Token) NULL;
  252.     } else {
  253.         fchmod(streamID, 0666);
  254.     }
  255.     }
  256.  
  257. gotStream:
  258.     pdevPtr = (Pdev *) malloc(sizeof(Pdev));
  259.     pdevPtr->stream.magic = PDEV_MAGIC;
  260.     pdevPtr->stream.streamID = streamID;
  261.     pdevPtr->stream.clientData = clientData;
  262.     pdevPtr->requestBufSize = requestBufSize;
  263.     pdevPtr->readBufSize = readBufSize;
  264.     List_Init(&pdevPtr->connectList);
  265.     pdevPtr->defaultService = (Pdev_CallBacks *)malloc(sizeof(Pdev_CallBacks));
  266.     if (service == (Pdev_CallBacks *)NULL) {
  267.     bzero((Address) pdevPtr->defaultService, sizeof(Pdev_CallBacks));
  268.     } else {
  269.     bcopy((Address) service, (Address) pdevPtr->defaultService,
  270.             sizeof(Pdev_CallBacks));
  271.     }
  272.     Fs_EventHandlerCreate(streamID, FS_READABLE, PdevControlRequest,
  273.         (ClientData) pdevPtr);
  274.  
  275.     return (Pdev_Token) pdevPtr;
  276. }
  277.  
  278. /*
  279.  *----------------------------------------------------------------------
  280.  *
  281.  * Pdev_Close --
  282.  *
  283.  *    Close down a pseudo-device and release all of the
  284.  *    state associated with it.
  285.  *
  286.  * Results:
  287.  *    None.
  288.  *
  289.  * Side effects:
  290.  *    Memory gets recycled, and clients on the other end of the
  291.  *    pseudo-device will probably terminate.  After this call,
  292.  *    the caller should never again use the pseudo-device.
  293.  *
  294.  *----------------------------------------------------------------------
  295.  */
  296.  
  297. void
  298. Pdev_Close(pdevToken)
  299.     Pdev_Token pdevToken;    /* Token identifying the pseudo-device.
  300.                  * This is returned from Pdev_Open. */
  301. {
  302.     register Pdev *pdevPtr = (Pdev *) pdevToken;
  303.     List_Links *listPtr;
  304.     register ServiceStream *srvPtr;
  305.  
  306.     while (!List_IsEmpty(&pdevPtr->connectList)) {
  307.     listPtr = List_First(&pdevPtr->connectList);
  308.     srvPtr = LIST_TO_SRVPTR(listPtr);
  309.     (void)PdevCleanup(srvPtr, FALSE);
  310.     }
  311.     Fs_EventHandlerDestroy(pdevPtr->stream.streamID);
  312.     close(pdevPtr->stream.streamID);
  313.     free((Address)pdevToken);
  314. }
  315.  
  316. /*
  317.  *----------------------------------------------------------------------
  318.  *
  319.  * Pdev_GetStreamID --
  320.  *
  321.  *    Return the descriptor associated with a master's pdev.  
  322.  *
  323.  * Results:
  324.  *    The streamID is returned.
  325.  *
  326.  * Side effects:
  327.  *    None.
  328.  *
  329.  *----------------------------------------------------------------------
  330.  */
  331.  
  332. int
  333. Pdev_GetStreamID(pdevToken)
  334.     Pdev_Token pdevToken;    /* Token identifying the pseudo-device.
  335.                  * This is returned from Pdev_Open. */
  336. {
  337.     register Pdev *pdevPtr = (Pdev *) pdevToken;
  338.     return(pdevPtr->stream.streamID);
  339. }
  340.  
  341.  
  342. /*
  343.  *----------------------------------------------------------------------
  344.  *
  345.  * PdevCleanup --
  346.  *
  347.  *    Called when a client has closed in order to
  348.  *    clean up any associated state.
  349.  *
  350.  * Results:
  351.  *    Returns the status from the close call-back.
  352.  *
  353.  * Side effects:
  354.  *    Calls the close-call back, then cleans up all state associated
  355.  *    with the pseudo-device.
  356.  *
  357.  *----------------------------------------------------------------------
  358.  */
  359.  
  360. static int
  361. PdevCleanup(srvPtr, sendReply)
  362.     register ServiceStream *srvPtr;    /* Service stream info. */
  363.     Boolean sendReply;            /* TRUE if we should reply to the
  364.                      * close request.  This is done in
  365.                      * normal termination.  FALSE means
  366.                      * no reply needed, used to close
  367.                      * pending connections when the
  368.                      * server is bailing out */
  369. {
  370.     int status;
  371.  
  372.     status = (*srvPtr->service->close)(&srvPtr->stream);
  373. #ifdef lint
  374.     status = PdevDefaultClose(&srvPtr->stream);
  375. #endif /* lint */
  376.  
  377.     if (sendReply) {
  378.     ReplyNoData(srvPtr, status, 0);
  379.     }
  380.     List_Remove(&srvPtr->links);
  381.     Fs_EventHandlerDestroy(srvPtr->stream.streamID);
  382.     close(srvPtr->stream.streamID);
  383.     free((char *) srvPtr->requestBuf);
  384.     if (srvPtr->service != (Pdev_CallBacks *)NULL) {
  385.     free((char *) srvPtr->service);
  386.     }
  387.     if (srvPtr->readBuf != NULL) {
  388.     free(srvPtr->readBuf);
  389.     }
  390.     if (srvPtr->ioctlOutBuf != NULL) {
  391.     free(srvPtr->ioctlOutBuf);
  392.     }
  393.     free((char *) srvPtr);
  394.     return status;
  395. }
  396.  
  397. /*
  398.  *----------------------------------------------------------------------
  399.  *
  400.  * PdevControlRequest --
  401.  *
  402.  *    This procedure is invoked by Fs_Dispatcher when the control
  403.  *    stream for a pseudo-device is readable.  This means that
  404.  *    a new stream is being opened on the pdev.
  405.  *
  406.  * Results:
  407.  *    None.
  408.  *
  409.  * Side effects:
  410.  *    Add a new service stream to the pdev.
  411.  *
  412.  *----------------------------------------------------------------------
  413.  */
  414.  
  415. static void
  416. PdevControlRequest(pdevPtr)
  417.     register Pdev *pdevPtr;    /* Pdev whose control stream is ready. */
  418. {
  419.     Pdev_Notify notify;
  420.     int numBytes;
  421.  
  422.     /*
  423.      * Read the control stream for a message containing a new streamID.
  424.      */
  425.  
  426.     numBytes = read(pdevPtr->stream.streamID, (char *) ¬ify, sizeof(notify));
  427.     if (numBytes != sizeof(notify)) {
  428.     panic("%s; status \"%s\", count %d\n",
  429.         "PdevControlRequest couldn't read control stream",
  430.         strerror(errno), numBytes);
  431.     }
  432.     if (notify.magic != PDEV_NOTIFY_MAGIC) {
  433.     panic("%s: %d\n", "PdevControlRequest got bad notify magic number",
  434.         notify.magic);
  435.     }
  436.     (void) PdevSetup(notify.newStreamID, (Address)pdevPtr,
  437.         &pdevPtr->connectList, pdevPtr->requestBufSize,
  438.         pdevPtr->readBufSize, (char *)0, pdevPtr->defaultService, 0);
  439. }
  440.  
  441. /*
  442.  *----------------------------------------------------------------------
  443.  *
  444.  * PdevSetup --
  445.  *
  446.  *    Set up state for a pseudo-device connection. This includes a request
  447.  *    buffer used by the kernel to pass client requests to us and a set
  448.  *    of service call-back procedures.
  449.  *    
  450.  * Results:
  451.  *    A pointer to the user's handle on the service stream.
  452.  *
  453.  * Side effects:
  454.  *    Allocates and initializes state.  Makes IOControls to set
  455.  *    attributes of the pdev connection.
  456.  *
  457.  *----------------------------------------------------------------------
  458.  */
  459.  
  460. Pdev_Stream *
  461. PdevSetup(streamID, backPointer, streamList, reqBufSize, readBufSize, readBuf, service, selectBits)
  462.     int streamID;        /* Service stream */
  463.     Address backPointer;    /* Pointer to global state */
  464.     List_Links *streamList;    /* List of pseudo-device streams */
  465.     int reqBufSize;        /* Size for the request buffer */
  466.     int readBufSize;        /* Size for the read buffer, if any */
  467.     char *readBuf;        /* The read buffer itself, NULL if it should
  468.                  * be allocated here */
  469.     Pdev_CallBacks *service;    /* Set of service call-backs */
  470.     int selectBits;        /* Initial select state of the connection */
  471. {
  472.     register ServiceStream *srvPtr;
  473.     Pdev_SetBufArgs setBuf;
  474.     int false = 0;
  475.  
  476.     srvPtr = (ServiceStream *) malloc(sizeof(ServiceStream));
  477.     List_InitElement(&srvPtr->links);
  478.     List_Insert(&srvPtr->links, LIST_ATFRONT(streamList));
  479.     srvPtr->stream.magic = PDEV_STREAM_MAGIC;
  480.     srvPtr->stream.streamID = streamID;
  481.     srvPtr->stream.clientData = 0;
  482.     srvPtr->parent = backPointer;
  483.     srvPtr->service = (Pdev_CallBacks *)malloc(sizeof(Pdev_CallBacks));
  484.     bcopy((Address) service, (Address) srvPtr->service,
  485.         sizeof(Pdev_CallBacks));
  486.     if (srvPtr->service->open == (int (*)())NULL) {
  487.     srvPtr->service->open = pdevDefaultCallBacks.open;
  488.     }
  489.     if (srvPtr->service->read == (int (*)())NULL) {
  490.     srvPtr->service->read = pdevDefaultCallBacks.read;
  491.     }
  492.     if (srvPtr->service->write == (int (*)())NULL) {
  493.     srvPtr->service->write = pdevDefaultCallBacks.write;
  494.     }
  495.     if (srvPtr->service->ioctl == (int (*)())NULL) {
  496.     srvPtr->service->ioctl = pdevDefaultCallBacks.ioctl;
  497.     }
  498.     if (srvPtr->service->close == (int (*)())NULL) {
  499.     srvPtr->service->close = pdevDefaultCallBacks.close;
  500.     }
  501.     if (srvPtr->service->getAttr == (int (*)())NULL) {
  502.     srvPtr->service->getAttr = pdevDefaultCallBacks.getAttr;
  503.     }
  504.     if (srvPtr->service->setAttr == (int (*)())NULL) {
  505.     srvPtr->service->setAttr = pdevDefaultCallBacks.setAttr;
  506.     }
  507.     if (readBufSize > 0) {
  508.     /*
  509.      * Server wants a read buffer.  We allocate it now and declare
  510.      * it to the kernel with the IOC_PDEV_SET_BUFS call below.
  511.      */
  512.     if (readBuf == NULL) {
  513.         srvPtr->readBuf = malloc(readBufSize);
  514.     } else {
  515.         srvPtr->readBuf = readBuf;
  516.     }
  517.     srvPtr->readBufSize = readBufSize;
  518.     } else {
  519.     /*
  520.      * No read buffering, but we will allocate a buffer for passing
  521.      * to the read service call-back later.
  522.      */
  523.     srvPtr->readBuf = NULL;
  524.     srvPtr->readBufSize = 0;
  525.     }
  526.     srvPtr->ioctlOutBuf = NULL;
  527.     srvPtr->ioctlBufSize = 0;
  528.  
  529.     reqBufSize = max(PDEV_REQUEST_BUF_SIZE, reqBufSize);
  530.     srvPtr->requestBuf = (Address) malloc(reqBufSize);
  531.     setBuf.requestBufAddr = srvPtr->requestBuf;
  532.     setBuf.requestBufSize = reqBufSize;
  533.     setBuf.readBufAddr = srvPtr->readBuf;
  534.     setBuf.readBufSize = srvPtr->readBufSize;
  535.     Fs_IOControl(streamID, IOC_PDEV_WRITE_BEHIND,
  536.             sizeof(int), (Address)&false, 0, (Address) NULL);
  537.     Fs_IOControl(streamID, IOC_PDEV_SET_BUF,
  538.             sizeof(Pdev_SetBufArgs), (Address)&setBuf,
  539.             0, (Address) NULL);
  540.     Fs_IOControl(streamID, IOC_PDEV_READY,
  541.             sizeof(int), (Address)&selectBits, 0, (Address) NULL);
  542.  
  543.     Fs_EventHandlerCreate(streamID, FS_READABLE, PdevServiceRequest,
  544.         (ClientData) srvPtr);
  545.  
  546.     return ((Pdev_Stream *)srvPtr);
  547. }
  548.  
  549. /*
  550.  *----------------------------------------------------------------------
  551.  *
  552.  * PdevServiceRequest --
  553.  *
  554.  *    This procedure is invoked by Fs_Dispatch when a request appears
  555.  *    for an service stream.   This procedure reads the request and
  556.  *    dispatches to a routine to handle the request.
  557.  *
  558.  * Results:
  559.  *    None.
  560.  *
  561.  * Side effects:
  562.  *    Makes the call-backs to the service procedures passed to Pdev_Open.
  563.  *    Generates pseudo-device replies to complete the protocol with
  564.  *    the kernel.
  565.  *
  566.  *----------------------------------------------------------------------
  567.  */
  568.  
  569. static void
  570. PdevServiceRequest(srvPtr)
  571.     register ServiceStream *srvPtr;    /* Application stream that has a
  572.                      * request ready for processing. */
  573. {
  574.     Pdev_BufPtrs bufPtrs;
  575.     Pdev_Signal signalInfo;
  576.     Pdev_Request *requestPtr;
  577.     Address dataPtr;        /* pointer to data following header */
  578.     Pdev_Reply reply;
  579.     int numBytes;
  580.     int status;
  581.     int selectBits;
  582.     int savedFirstByte;
  583.  
  584.     /*
  585.      * Read the current pointers for the request buffer.
  586.      */
  587.  
  588.     numBytes = read(srvPtr->stream.streamID, (char *) &bufPtrs,
  589.         sizeof(Pdev_BufPtrs));
  590.     if (numBytes != sizeof(Pdev_BufPtrs)) {
  591.     panic("%s; status \"%s\", count %d\n",
  592.         "PdevServiceRequest had trouble reading request buffer pointers",
  593.         strerror(errno), numBytes);
  594.     }
  595.     if (bufPtrs.magic != PDEV_BUF_PTR_MAGIC) {
  596.     panic("%s: %d\n", "PdevServiceRequest got bad pointer magic number",
  597.         bufPtrs.magic);
  598.     }
  599.     savedFirstByte = bufPtrs.requestFirstByte;
  600.     /*
  601.      * While there are still requests in the buffer, service them.
  602.      */
  603.     while (bufPtrs.requestFirstByte < bufPtrs.requestLastByte) {
  604.     requestPtr =
  605.         (Pdev_Request *)&srvPtr->requestBuf[bufPtrs.requestFirstByte];
  606.     if (requestPtr->hdr.magic != PDEV_REQUEST_MAGIC) {
  607.         printf("PdevServiceRequest, alignment error: firstByte %d currentByte %d lastByte %d magic %x\n",
  608.           savedFirstByte,
  609.           bufPtrs.requestFirstByte, bufPtrs.requestLastByte,
  610.           requestPtr->hdr.magic);
  611.         /*
  612.          * Ignore bogus request.
  613.          */
  614.         bufPtrs.requestFirstByte = bufPtrs.requestLastByte + 1;
  615.         break;
  616.     }
  617.     dataPtr = (Address)((int)requestPtr + sizeof(Pdev_Request));
  618.     signalInfo.signal = 0;
  619.     signalInfo.code = 0;
  620.  
  621.     switch (requestPtr->hdr.operation) {
  622.         case PDEV_OPEN: {
  623.         /*
  624.          * This is the first operation on a pseudo-device.  The
  625.          * server can set srvPtr->private here, which will be
  626.          * passed into the other handlers.
  627.          */
  628.         Pdev *pdevPtr;
  629.         if (pdev_Trace) {
  630.             fprintf(stderr, "OPEN %d: uid %d use %x",
  631.                 srvPtr->stream.streamID,
  632.                 requestPtr->param.open.uid,
  633.                 requestPtr->param.open.flags);
  634.         }
  635.         pdevPtr = (Pdev *)srvPtr->parent;
  636.         status = (*srvPtr->service->open)
  637.                 (pdevPtr->stream.clientData, &srvPtr->stream,
  638.                 srvPtr->readBuf,
  639.                 requestPtr->param.open.flags,
  640.                 requestPtr->param.open.pid,
  641.                 requestPtr->param.open.hostID,
  642.                 requestPtr->param.open.uid,
  643.                 &selectBits);
  644. #ifdef lint
  645.         status = PdevDefaultOpen(pdevPtr->stream.clientData, &srvPtr->stream,
  646.                 srvPtr->readBuf,
  647.                 requestPtr->param.open.flags,
  648.                 requestPtr->param.open.pid,
  649.                 requestPtr->param.open.hostID,
  650.                 requestPtr->param.open.uid,
  651.                 &selectBits);
  652. #endif /* lint */
  653.         ReplyNoData(srvPtr, status, selectBits);
  654.         break;
  655.         }
  656.         case PDEV_CLOSE:
  657.         if (pdev_Trace) {
  658.             fprintf(stderr, "CLOSE %d", srvPtr->stream.streamID);
  659.         }
  660.         status = PdevCleanup(srvPtr, TRUE);
  661.         break;
  662.         case PDEV_READ: {
  663.         /*
  664.          * For reading we pass in a pre-allocated buffer, but also
  665.          * allow the read procedure to use a different buffer.  If it
  666.          * does change the buffer it also indicates if we should
  667.          * free the new buffer after we reply.  We hold onto our
  668.          * own srvPtr->readBuf until the connection is closed.
  669.          */
  670.         Boolean freeIt = FALSE;
  671.  
  672.         if (pdev_Trace) {
  673.             fprintf(stderr, "READ %d bytes at offset %d\n",
  674.             requestPtr->hdr.replySize,
  675.             requestPtr->param.read.offset);
  676.         }
  677.  
  678.         reply.replySize = requestPtr->hdr.replySize;
  679.         if (reply.replySize > srvPtr->readBufSize) {
  680.             /*
  681.              * Increase the read buffer size.
  682.              */
  683.             if (srvPtr->readBuf != NULL) {
  684.             free(srvPtr->readBuf);
  685.             }
  686.             srvPtr->readBuf = malloc(reply.replySize);
  687.             srvPtr->readBufSize = reply.replySize;
  688.         }
  689.         requestPtr->param.read.buffer = srvPtr->readBuf;
  690.         status = (*srvPtr->service->read)(&srvPtr->stream,
  691.                 &requestPtr->param.read, &freeIt,
  692.                 &reply.selectBits,
  693.                 &signalInfo);
  694. #ifdef lint
  695.         status = PdevDefaultRead(&srvPtr->stream,
  696.                 &requestPtr->param.read, &freeIt,
  697.                 &reply.selectBits,
  698.                 &signalInfo);
  699. #endif /* lint */
  700.  
  701.         reply.replySize = requestPtr->param.read.length;
  702.         reply.replyBuf = requestPtr->param.read.buffer;
  703.         ReplyWithData(srvPtr, status, &reply, &signalInfo);
  704.         if (freeIt &&
  705.             (requestPtr->param.read.buffer != srvPtr->readBuf)) {
  706.             free(requestPtr->param.read.buffer);
  707.         }
  708.         break;
  709.         }
  710.         case PDEV_WRITE_ASYNC:
  711.         case PDEV_WRITE: {
  712.         if (pdev_Trace) {
  713.             fprintf(stderr, "WRITE %d bytes at offset %d",
  714.             requestPtr->hdr.requestSize,
  715.             requestPtr->param.read.offset);
  716.         }
  717.         requestPtr->param.write.buffer = dataPtr;
  718.         status = (*srvPtr->service->write)(&srvPtr->stream,
  719.                 (requestPtr->hdr.operation == PDEV_WRITE_ASYNC),
  720.                 &requestPtr->param.write,
  721.                 &reply.selectBits,
  722.                 &signalInfo);
  723. #ifdef lint
  724.         status = PdevDefaultWrite(&srvPtr->stream,
  725.                 (requestPtr->hdr.operation == PDEV_WRITE_ASYNC),
  726.                 &requestPtr->param.write,
  727.                 &reply.selectBits,
  728.                 &signalInfo);
  729. #endif /* lint */
  730.         if (requestPtr->hdr.operation == PDEV_WRITE) {
  731.             reply.replySize = sizeof(int);
  732.             reply.replyBuf = (Address)&requestPtr->param.write.length;
  733.             ReplyWithData(srvPtr, status, &reply, &signalInfo);
  734.         }
  735.         break;
  736.         }
  737.         case PDEV_IOCTL: {
  738.         if (pdev_Trace) {
  739.             fprintf(stderr, "IOCTL %d", requestPtr->param.ioctl.command);
  740.         }
  741.         /*
  742.          * The kernel sets up the sizes of the two buffers,
  743.          * but we have our own notion of where they are.
  744.          * We grow the out buffer if needed, for example,
  745.          * and the inBuffer is sitting in the request buffer at dataPtr.
  746.          */
  747.         reply.replySize = requestPtr->hdr.replySize;
  748.         if (reply.replySize > srvPtr->ioctlBufSize) {
  749.             if (srvPtr->ioctlOutBuf != NULL) {
  750.             free(srvPtr->ioctlOutBuf);
  751.             }
  752.             srvPtr->ioctlOutBuf = malloc(reply.replySize);
  753.             srvPtr->ioctlBufSize = reply.replySize;
  754.         }
  755.         requestPtr->param.ioctl.inBuffer = dataPtr;
  756.         requestPtr->param.ioctl.outBuffer = srvPtr->ioctlOutBuf;
  757.         status = (*srvPtr->service->ioctl)(&srvPtr->stream,
  758.                  &requestPtr->param.ioctl,
  759.                  &reply.selectBits,
  760.                  &signalInfo);
  761. #ifdef lint
  762.         status = PdevDefaultIoctl(&srvPtr->stream,
  763.                  &requestPtr->param.ioctl,
  764.                  &reply.selectBits,
  765.                  &signalInfo);
  766. #endif /* lint */
  767.         reply.replyBuf = srvPtr->ioctlOutBuf;
  768.         reply.replySize = requestPtr->param.ioctl.outBufSize;
  769.         ReplyWithData(srvPtr, status, &reply, &signalInfo);
  770.         break;
  771.         }
  772.         case PDEV_GET_ATTR: {
  773.         Fs_Attributes attr;
  774.  
  775.         if (pdev_Trace) {
  776.             fprintf(stderr, "GET ATTR");
  777.         }
  778.         status = (*srvPtr->service->getAttr)(&srvPtr->stream,
  779.                 &attr, &reply.selectBits);
  780. #ifdef lint
  781.         status = PdevDefaultGetAttr(&srvPtr->stream,
  782.                 &attr, &reply.selectBits);
  783. #endif /* lint */
  784.         if (status == SUCCESS) {
  785.             reply.replyBuf = (Address)&attr;
  786.             reply.replySize = sizeof(Fs_Attributes);
  787.             ReplyWithData(srvPtr, status, &reply, (Pdev_Signal *)NIL);
  788.         } else {
  789.             ReplyNoData(srvPtr, status, reply.selectBits);
  790.         }
  791.         break;
  792.         }
  793.         case PDEV_SET_ATTR: {
  794.         if (pdev_Trace) {
  795.             fprintf(stderr, "SET ATTR %x", requestPtr->param.setAttr.flags);
  796.         }
  797.         status = (*srvPtr->service->setAttr)(&srvPtr->stream,
  798.                 requestPtr->param.setAttr.flags,
  799.                 requestPtr->param.setAttr.uid,
  800.                 requestPtr->param.setAttr.gid,
  801.                 (Fs_Attributes *)dataPtr, &reply.selectBits);
  802. #ifdef lint
  803.         status = PdevDefaultSetAttr(&srvPtr->stream,
  804.                 requestPtr->param.setAttr.flags,
  805.                 requestPtr->param.setAttr.uid,
  806.                 requestPtr->param.setAttr.gid,
  807.                 (Fs_Attributes *)dataPtr, &reply.selectBits);
  808. #endif /* lint */
  809.         ReplyNoData(srvPtr, status, reply.selectBits);
  810.         break;
  811.         }
  812.         default:
  813.         panic("PdevServiceRequest: bad request on request stream: %d\n",
  814.             requestPtr->hdr.operation);
  815.     }
  816.     if (pdev_Trace) {
  817.         fprintf(stderr, " Returns %x\n", status);
  818.     }
  819.     /*
  820.      * Move to the next request message.
  821.      */
  822.     bufPtrs.requestFirstByte += requestPtr->hdr.messageSize;
  823.     }
  824.     /*
  825.      * Tell the kernel we processed the requests.
  826.      */
  827.     Fs_IOControl(srvPtr->stream.streamID, IOC_PDEV_SET_PTRS,
  828.             sizeof(Pdev_BufPtrs), (Address)&bufPtrs,
  829.             0, (Address) NULL);
  830. }
  831.  
  832. /*
  833.  *----------------------------------------------------------------------
  834.  *
  835.  * ReplyNoData --
  836.  *
  837.  *    Send a reply back with no data;  just a return status.  This
  838.  *    procedure is most often used for error returns.
  839.  *
  840.  * Results:
  841.  *    None.
  842.  *
  843.  * Side effects:
  844.  *    The application will receive status as the return from the
  845.  *    system call it invoked.
  846.  *
  847.  *----------------------------------------------------------------------
  848.  */
  849.  
  850. static void
  851. ReplyNoData(srvPtr, status, selectBits)
  852.     ServiceStream *srvPtr;    /* Application stream info. */
  853.     int status;    /* Error code to send to application. */
  854.     int selectBits;        /* Current select state for the stream */
  855. {
  856.     Pdev_Reply reply;
  857.  
  858.     reply.magic = PDEV_REPLY_MAGIC;
  859.     reply.selectBits = selectBits;
  860.     if (status == EWOULDBLOCK) {
  861.     status = FS_WOULD_BLOCK;
  862.     } else {
  863.     status = Compat_MapToSprite(status);
  864.     }
  865.     reply.status = status;
  866.     reply.replySize = 0;
  867.     reply.replyBuf = NULL;
  868.     reply.signal = 0;
  869.     reply.code = 0;
  870.     status = Fs_IOControl(srvPtr->stream.streamID, IOC_PDEV_REPLY,
  871.         sizeof(Pdev_Reply), (Address) &reply, 0, (Address) NULL);
  872.     if (status != SUCCESS) {
  873.     panic("%s; status \"%s\"\n", "Reply couldn't send pdev reply",
  874.         Stat_GetMsg(status));
  875.     }
  876. }
  877.  
  878. /*
  879.  *----------------------------------------------------------------------
  880.  *
  881.  * ReplyWithData --
  882.  *
  883.  *    Send a reply back along with some data.
  884.  *
  885.  * Results:
  886.  *    None.
  887.  *
  888.  * Side effects:
  889.  *    The application will receive status as the return from the
  890.  *    system call it invoked.
  891.  *
  892.  *----------------------------------------------------------------------
  893.  */
  894.  
  895. static void
  896. ReplyWithData(srvPtr, status, replyPtr, sigPtr)
  897.     ServiceStream *srvPtr;    /* Application stream info. */
  898.     int status;            /* Error code to send to application. */
  899.     Pdev_Reply *replyPtr;    /* Partially completed reply.  The replySize,
  900.                  * data area, and selectBits should be set. */
  901.     Pdev_Signal *sigPtr;    /* Signal to return, if any */
  902. {
  903.     if (status == EWOULDBLOCK) {
  904.     status = FS_WOULD_BLOCK;
  905.     } else {
  906.     status = Compat_MapToSprite(status);
  907.     }
  908.     if (sigPtr != (Pdev_Signal *)NIL) {
  909.     replyPtr->signal = sigPtr->signal;
  910.     replyPtr->code = sigPtr->code;
  911.     } else {
  912.     replyPtr->signal = 0;
  913.     replyPtr->code = 0;
  914.     }
  915.     if (replyPtr->replySize <= PDEV_SMALL_DATA_LIMIT) {
  916.     Pdev_ReplyData replyData;
  917.  
  918.     replyData.magic = PDEV_REPLY_DATA_MAGIC;
  919.     replyData.status = status;
  920.     replyData.selectBits = replyPtr->selectBits;
  921.     replyData.replySize = replyPtr->replySize;
  922.     replyData.signal = replyPtr->signal;
  923.     replyData.code = replyPtr->code;
  924.     bcopy(replyPtr->replyBuf, replyData.data, replyPtr->replySize);
  925.     status = Fs_IOControl(srvPtr->stream.streamID, IOC_PDEV_SMALL_REPLY,
  926.         sizeof(Pdev_ReplyData), (Address)&replyData, 0, (Address) NULL);
  927.     } else {
  928.     replyPtr->magic = PDEV_REPLY_MAGIC;
  929.     replyPtr->status = status;
  930.     status = Fs_IOControl(srvPtr->stream.streamID, IOC_PDEV_REPLY,
  931.             sizeof(Pdev_Reply), (Address) replyPtr, 0, (Address) NULL);
  932.     }
  933.     if (status != SUCCESS) {
  934.     panic("%s; status \"%s\"\n", "ReplyWithData couldn't send pdev reply",
  935.         Stat_GetMsg(status));
  936.     }
  937. }
  938.  
  939. /*
  940.  *----------------------------------------------------------------------
  941.  *
  942.  * Pdev_EnumStreams --
  943.  *
  944.  *    Apply a function to all service streams associated with a pdev.
  945.  *
  946.  * Results:
  947.  *    0 means all the applications of the function returned 0 as well.
  948.  *    If the function returns non-zero when applied to a stream then
  949.  *    the enumeration is stopped and that value is returned.
  950.  *
  951.  * Side effects:
  952.  *    None here.
  953.  *
  954.  *----------------------------------------------------------------------
  955.  */
  956.  
  957. int
  958. Pdev_EnumStreams(pdevToken, func, clientData)
  959.     Pdev_Token pdevToken;
  960.     int (*func)();
  961.     ClientData clientData;
  962. {
  963.     register Pdev *pdevPtr = (Pdev *)pdevToken;
  964.     register List_Links *listPtr;
  965.     register ServiceStream *srvPtr;
  966.     register int status;
  967.  
  968.     if (pdevPtr->stream.magic != (unsigned int)PDEV_MAGIC) {
  969.     fprintf(stderr, "Pdev_EnumStreams passed bad pdevToken\n");
  970.     return -1;
  971.     }
  972.     LIST_FORALL(&pdevPtr->connectList, listPtr) {
  973.     srvPtr = LIST_TO_SRVPTR(listPtr);
  974.     status = (*func)((Pdev_Stream *)srvPtr, clientData);
  975.     if (status != 0) {
  976.         return(status);
  977.     }
  978.     }
  979.     return(0);
  980. }
  981.  
  982.  
  983. /*
  984.  *----------------------------------------------------------------------
  985.  *
  986.  * Pfs_SetDefaultHandler --
  987.  *
  988.  *    Set a default handler for a particular PDEV request.  If the handler is
  989.  *    NULL then a default procedure replaces the existing handler.
  990.  *    The default handlers are used when new connections are established
  991.  *    to the pseudo-device.
  992.  * 
  993.  * Results:
  994.  *    The old handler.
  995.  *
  996.  * Side effects:
  997.  *    Updates the call-back list.
  998.  *
  999.  *----------------------------------------------------------------------
  1000.  */
  1001. int (*
  1002. Pdev_SetDefaultHandler(token, operation, handler))()
  1003.     Pdev_Token token;        /* Returned from Pdev_Open */
  1004.     int operation;        /* Which operation to set the handler for */
  1005.     int (*handler)();        /* The callback procedure */
  1006. {
  1007.     register Pdev        *pdevPtr = (Pdev *)token;
  1008.     register int        (*oldHandler)();
  1009.  
  1010.     if (pdevPtr->stream.magic != (unsigned int)PDEV_MAGIC) {
  1011.     fprintf(stderr, "Bad token passed to Pdev_SetHandler\n");
  1012.     return (int (*)())NULL;
  1013.     }
  1014.  
  1015.     oldHandler = SetHandler(pdevPtr->defaultService, operation, handler);
  1016.     return oldHandler;
  1017. }
  1018.  
  1019. /*
  1020.  *----------------------------------------------------------------------
  1021.  *
  1022.  * Pfs_SetStreamHandler --
  1023.  *
  1024.  *    Set a handler for a particular stream and PDEV request.  If the handler
  1025.  *    is NULL then a default procedure replaces the existing handler.
  1026.  *    This call only affects the handler for the given stream to the
  1027.  *    pseudo-device.
  1028.  * 
  1029.  * Results:
  1030.  *    The old handler.
  1031.  *
  1032.  * Side effects:
  1033.  *    Updates the call-back list.
  1034.  *
  1035.  *----------------------------------------------------------------------
  1036.  */
  1037. int (*
  1038. Pdev_SetStreamHandler(streamPtr, operation, handler))()
  1039.     Pdev_Stream *streamPtr;/* Handler for stream to pseudo-device */
  1040.     int operation;        /* Which operation to set the handler for */
  1041.     int (*handler)();        /* The callback procedure */
  1042. {
  1043.     register ServiceStream    *srvPtr = (ServiceStream *)streamPtr;
  1044.     register int        (*oldHandler)();
  1045.  
  1046.     if (srvPtr->stream.magic != (unsigned int)PDEV_STREAM_MAGIC) {
  1047.     fprintf(stderr, "Bad token passed to Pdev_SetHandler\n");
  1048.     return (int (*)())NULL;
  1049.     }
  1050.  
  1051.     oldHandler = SetHandler(srvPtr->service, operation, handler);
  1052.     return oldHandler;
  1053. }
  1054.  
  1055. /*
  1056.  *----------------------------------------------------------------------
  1057.  *
  1058.  * SetHandler --
  1059.  *
  1060.  *    Set the handler for a pseudo-device operation and return the
  1061.  *    old handler.
  1062.  *
  1063.  * Results:
  1064.  *    The old handler.
  1065.  *
  1066.  * Side effects:
  1067.  *    Change the handler.
  1068.  *
  1069.  *----------------------------------------------------------------------
  1070.  */
  1071.  
  1072. static int (*
  1073. SetHandler(service, operation, handler))()
  1074.     Pdev_CallBacks *service;
  1075.     int operation;
  1076.     int (*handler)();
  1077. {
  1078.     int (*oldHandler)();
  1079.  
  1080.     switch (operation) {
  1081.     case PDEV_OPEN:
  1082.         oldHandler = service->open;
  1083.         if (handler == (int (*)())NULL) {
  1084.         service->open = pdevDefaultCallBacks.open;
  1085.         } else {
  1086.         service->open = handler;
  1087.         }
  1088.         break;
  1089.     case PDEV_CLOSE:
  1090.         oldHandler = service->close;
  1091.         if (handler == (int (*)())NULL) {
  1092.         service->close = pdevDefaultCallBacks.close;
  1093.         } else {
  1094.         service->close = handler;
  1095.         }
  1096.         break;
  1097.     case PDEV_READ:
  1098.         oldHandler = service->read;
  1099.         if (handler == (int (*)())NULL) {
  1100.         service->read = pdevDefaultCallBacks.read;
  1101.         } else {
  1102.         service->read = handler;
  1103.         }
  1104.         break;
  1105.     case PDEV_WRITE:
  1106.         oldHandler = service->write;
  1107.         if (handler == (int (*)())NULL) {
  1108.         service->write = pdevDefaultCallBacks.write;
  1109.         } else {
  1110.         service->write = handler;
  1111.         }
  1112.         break;
  1113.     case PDEV_IOCTL:
  1114.         oldHandler = service->ioctl;
  1115.         if (handler == (int (*)())NULL) {
  1116.         service->ioctl = pdevDefaultCallBacks.ioctl;
  1117.         } else {
  1118.         service->ioctl = handler;
  1119.         }
  1120.         break;
  1121.     case PDEV_GET_ATTR:
  1122.         oldHandler = service->getAttr;
  1123.         if (handler == (int (*)())NULL) {
  1124.         service->getAttr = pdevDefaultCallBacks.getAttr;
  1125.         } else {
  1126.         service->getAttr = handler;
  1127.         }
  1128.         break;
  1129.     case PDEV_SET_ATTR:
  1130.         oldHandler = service->setAttr;
  1131.         if (handler == (int (*)())NULL) {
  1132.         service->setAttr = pdevDefaultCallBacks.setAttr;
  1133.         } else {
  1134.         service->setAttr = handler;
  1135.         }
  1136.         break;
  1137.     default:
  1138.         fprintf(stderr, "Bad operation passed to Pdev_SetHandler");
  1139.         oldHandler = (int (*)())NULL;
  1140.         break;
  1141.     }
  1142.     return oldHandler;
  1143. }
  1144.  
  1145. /*
  1146.  *----------------------------------------------------------------------
  1147.  *
  1148.  * PdevDefaultOpen --
  1149.  *
  1150.  *    Default procedure is called when an PDEV_OPEN request is
  1151.  *    received over an service stream.
  1152.  *
  1153.  * Results:
  1154.  *    Returns SUCCESS and the select state of the pseudo-device.
  1155.  *
  1156.  * Side effects:
  1157.  *    None.
  1158.  *
  1159.  *----------------------------------------------------------------------
  1160.  */
  1161. /*ARGSUSED*/
  1162. static int
  1163. PdevDefaultOpen(clientData, streamPtr, readBuf, flags, procID, hostID,
  1164.     uid, selectBitsPtr)
  1165.     ClientData clientData;    /* Client data associated with pseudo-device */
  1166.     Pdev_Stream *streamPtr;    /* Identifies open stream */
  1167.     char *readBuf;        /* Optional read buffer */
  1168.     int flags;            /* Flags passed to open system call */
  1169.     int procID;            /* Process ID doing the open */
  1170.     int hostID;            /* Host on which process is executing */
  1171.     int uid;            /* User id of process */
  1172.     int *selectBitsPtr;        /* Return - select state of pseudo-device */
  1173. {
  1174.     *selectBitsPtr = FS_READABLE | FS_WRITABLE;
  1175.     return(SUCCESS);
  1176. }
  1177.  
  1178. /*
  1179.  *----------------------------------------------------------------------
  1180.  *
  1181.  * PdevDefaultClose --
  1182.  *
  1183.  *    Default procedure is called when an PDEV_CLOSE request is
  1184.  *    received over an service stream.
  1185.  *
  1186.  * Results:
  1187.  *    Returns SUCCESS and the select state of the pseudo-device.
  1188.  *
  1189.  * Side effects:
  1190.  *    None.
  1191.  *
  1192.  *----------------------------------------------------------------------
  1193.  */
  1194. /*ARGSUSED*/
  1195. static int
  1196. PdevDefaultClose(streamPtr)
  1197.     Pdev_Stream *streamPtr;
  1198. {
  1199.     return(SUCCESS);
  1200. }
  1201.  
  1202. /*
  1203.  *----------------------------------------------------------------------
  1204.  *
  1205.  * PdevDefaultRead --
  1206.  *
  1207.  *    The default read procedure.  This simulates EOF by returning
  1208.  *    SUCCESS but no characters.
  1209.  *
  1210.  * Results:
  1211.  *    None.
  1212.  *
  1213.  * Side effects:
  1214.  *    None.
  1215.  *
  1216.  *----------------------------------------------------------------------
  1217.  */
  1218. /*ARGSUSED*/
  1219. static int
  1220. PdevDefaultRead(streamPtr, readPtr, freeItPtr, selectBitsPtr, sigPtr)
  1221.     Pdev_Stream *streamPtr;    /* Service stream. */
  1222.     Pdev_RWParam *readPtr;    /* Read parameter block. */
  1223.     Boolean *freeItPtr;        /* Return indicates if *bufferPtr is malloc'd */
  1224.     int *selectBitsPtr;        /* Return - the select state of the pdev */
  1225.     Pdev_Signal *sigPtr;    /* Return - signal to generate. */
  1226. {
  1227.     *freeItPtr = FALSE;
  1228.     readPtr->length = 0;
  1229.     *selectBitsPtr = FS_READABLE | FS_WRITABLE;
  1230.     return(SUCCESS);
  1231. }
  1232.  
  1233. /*
  1234.  *----------------------------------------------------------------------
  1235.  *
  1236.  * PdevDefaultWrite --
  1237.  *
  1238.  *    The default write procedure.  This accepts and discards all data.
  1239.  *
  1240.  * Results:
  1241.  *    None.
  1242.  *
  1243.  * Side effects:
  1244.  *    None.
  1245.  *
  1246.  *----------------------------------------------------------------------
  1247.  */
  1248.  
  1249. /*ARGSUSED*/
  1250. static int
  1251. PdevDefaultWrite(streamPtr, async, writePtr, selectBitsPtr, sigPtr)
  1252.     Pdev_Stream *streamPtr;    /* Private data */
  1253.     int async;            /* TRUE if asynchronous and no reply needed */
  1254.     Pdev_RWParam *writePtr;    /* Write parameter block. */
  1255.     int *selectBitsPtr;        /* Result - select state of the pseudo-device */
  1256.     Pdev_Signal *sigPtr;    /* Return - signal to generate. */
  1257. {
  1258.     *selectBitsPtr = FS_READABLE | FS_WRITABLE;
  1259.     return(SUCCESS);
  1260. }
  1261.  
  1262. /*
  1263.  *----------------------------------------------------------------------
  1264.  *
  1265.  * PdevDefaultIoctl --
  1266.  *
  1267.  *    The default IOControl handling procedure called when an
  1268.  *    PDEV_IOCONTROL request is received over a request stream.
  1269.  *
  1270.  * Results:
  1271.  *    None.
  1272.  *
  1273.  * Side effects
  1274.  *    None.
  1275.  *
  1276.  *----------------------------------------------------------------------
  1277.  */
  1278. /*ARGSUSED*/
  1279. static int
  1280. PdevDefaultIoctl(streamPtr, ioctlPtr, selectBitsPtr, sigPtr)
  1281.     Pdev_Stream *streamPtr;    /* Stream to service. */
  1282.     Pdev_IOCParam *ioctlPtr;    /* ioctl parameter block. */
  1283.     int *selectBitsPtr;        /* Return - select state of pdev. */
  1284.     Pdev_Signal *sigPtr;    /* Return - signal to generate. */
  1285. {
  1286.     ioctlPtr->outBufSize = 0;
  1287.     *selectBitsPtr = FS_READABLE | FS_WRITABLE;
  1288.     return(SUCCESS);
  1289. }
  1290.  
  1291. /*
  1292.  *----------------------------------------------------------------------
  1293.  *
  1294.  * PdevDefaultGetAttr --
  1295.  *
  1296.  *    The default GetAttributes handling procedure called when an
  1297.  *    PDEV_GET_ATTR request is received over a request stream.
  1298.  *
  1299.  * Results:
  1300.  *    None.
  1301.  *
  1302.  * Side effects
  1303.  *    None.
  1304.  *
  1305.  *----------------------------------------------------------------------
  1306.  */
  1307. /*ARGSUSED*/
  1308. static int
  1309. PdevDefaultGetAttr(streamPtr, attrPtr, selectBitsPtr)
  1310.     Pdev_Stream *streamPtr;
  1311.     Fs_Attributes *attrPtr;
  1312.     int *selectBitsPtr;
  1313. {
  1314.     bzero((Address)attrPtr, sizeof(Fs_Attributes));
  1315.     attrPtr->fileNumber = (int)streamPtr->clientData;
  1316.     attrPtr->permissions = 0644;
  1317.     attrPtr->type = FS_FILE;
  1318.     *selectBitsPtr = FS_READABLE | FS_WRITABLE;
  1319.     return(SUCCESS);
  1320. }
  1321.  
  1322. /*
  1323.  *----------------------------------------------------------------------
  1324.  *
  1325.  * PdevDefaultSetAttr --
  1326.  *
  1327.  *    The default GetAttributes handling procedure called when an
  1328.  *    PDEV_SET_ATTR request is received over a request stream.
  1329.  *
  1330.  * Results:
  1331.  *    None.
  1332.  *
  1333.  * Side effects
  1334.  *    None.
  1335.  *
  1336.  *----------------------------------------------------------------------
  1337.  */
  1338. /*ARGSUSED*/
  1339. static int
  1340. PdevDefaultSetAttr(streamPtr, flags, uid, gid, attrPtr, selectBitsPtr)
  1341.     Pdev_Stream *streamPtr;
  1342.     int flags;
  1343.     int uid;
  1344.     int gid;
  1345.     Fs_Attributes *attrPtr;
  1346.     int *selectBitsPtr;
  1347. {
  1348.     *selectBitsPtr = FS_READABLE | FS_WRITABLE;
  1349.     return(SUCCESS);
  1350. }
  1351.